package org.itstack.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.itstack.model.aggregates.TreeRich;
import org.itstack.model.vo.TreeNode;
import org.itstack.model.vo.TreeNodeLink;
import org.itstack.model.vo.TreeRoot;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 决策树配置加载器
 * 从JSON配置文件加载决策树配置
 */
public class DecisionTreeConfigLoader {
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    /**
     * 从JSON文件加载决策树配置
     * @param configPath 配置文件路径
     * @return 决策树实例
     */
    public static TreeRich loadFromJson(String configPath) {
        try {
            InputStream inputStream = DecisionTreeConfigLoader.class.getClassLoader()
                    .getResourceAsStream(configPath);
            
            if (inputStream == null) {
                throw new RuntimeException("配置文件不存在: " + configPath);
            }
            
            // 解析JSON配置
            DecisionTreeConfig config = objectMapper.readValue(inputStream, DecisionTreeConfig.class);
            
            // 构建决策树
            return buildTreeRich(config);
            
        } catch (Exception e) {
            throw new RuntimeException("加载配置文件失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 从JSON字符串加载决策树配置
     * @param jsonConfig JSON配置字符串
     * @return 决策树实例
     */
    public static TreeRich loadFromJsonString(String jsonConfig) {
        try {
            DecisionTreeConfig config = objectMapper.readValue(jsonConfig, DecisionTreeConfig.class);
            return buildTreeRich(config);
        } catch (Exception e) {
            throw new RuntimeException("解析JSON配置失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 构建决策树
     */
    private static TreeRich buildTreeRich(DecisionTreeConfig config) {
        // 构建树根
        TreeRoot treeRoot = new TreeRoot();
        treeRoot.setTreeId(config.getTreeRoot().getTreeId());
        treeRoot.setTreeName(config.getTreeRoot().getTreeName());
        treeRoot.setTreeRootNodeId(config.getTreeRoot().getTreeRootNodeId());
        
        // 构建节点映射
        Map<Long, TreeNode> treeNodeMap = new HashMap<>();
        
        for (TreeNodeConfig nodeConfig : config.getTreeNodes()) {
            TreeNode treeNode = new TreeNode();
            treeNode.setTreeId(nodeConfig.getTreeId());
            treeNode.setTreeNodeId(nodeConfig.getTreeNodeId());
            treeNode.setNodeType(nodeConfig.getNodeType());
            treeNode.setNodeValue(nodeConfig.getNodeValue());
            treeNode.setRuleKey(nodeConfig.getRuleKey());
            treeNode.setRuleDesc(nodeConfig.getRuleDesc());
            
            // 构建节点链接
            if (nodeConfig.getTreeNodeLinks() != null) {
                List<TreeNodeLink> links = nodeConfig.getTreeNodeLinks().stream()
                        .map(linkConfig -> {
                            TreeNodeLink link = new TreeNodeLink();
                            link.setNodeIdFrom(linkConfig.getNodeIdFrom());
                            link.setNodeIdTo(linkConfig.getNodeIdTo());
                            link.setRuleLimitType(linkConfig.getRuleLimitType());
                            link.setRuleLimitValue(linkConfig.getRuleLimitValue());
                            return link;
                        })
                        .toList();
                treeNode.setTreeNodeLinkList(links);
            }
            
            treeNodeMap.put(treeNode.getTreeNodeId(), treeNode);
        }
        
        return new TreeRich(treeRoot, treeNodeMap);
    }
    
    /**
     * 配置类
     */
    public static class DecisionTreeConfig {
        private TreeRootConfig treeRoot;
        private List<TreeNodeConfig> treeNodes;
        private Map<String, String> filters;
        private CacheConfig cacheConfig;
        
        // Getters and Setters
        public TreeRootConfig getTreeRoot() { return treeRoot; }
        public void setTreeRoot(TreeRootConfig treeRoot) { this.treeRoot = treeRoot; }
        
        public List<TreeNodeConfig> getTreeNodes() { return treeNodes; }
        public void setTreeNodes(List<TreeNodeConfig> treeNodes) { this.treeNodes = treeNodes; }
        
        public Map<String, String> getFilters() { return filters; }
        public void setFilters(Map<String, String> filters) { this.filters = filters; }
        
        public CacheConfig getCacheConfig() { return cacheConfig; }
        public void setCacheConfig(CacheConfig cacheConfig) { this.cacheConfig = cacheConfig; }
    }
    
    /**
     * 树根配置类
     */
    public static class TreeRootConfig {
        private Long treeId;
        private String treeName;
        private Long treeRootNodeId;
        
        // Getters and Setters
        public Long getTreeId() { return treeId; }
        public void setTreeId(Long treeId) { this.treeId = treeId; }
        
        public String getTreeName() { return treeName; }
        public void setTreeName(String treeName) { this.treeName = treeName; }
        
        public Long getTreeRootNodeId() { return treeRootNodeId; }
        public void setTreeRootNodeId(Long treeRootNodeId) { this.treeRootNodeId = treeRootNodeId; }
    }
    
    /**
     * 树节点配置类
     */
    public static class TreeNodeConfig {
        private Long treeId;
        private Long treeNodeId;
        private Integer nodeType;
        private String nodeValue;
        private String ruleKey;
        private String ruleDesc;
        private List<TreeNodeLinkConfig> treeNodeLinks;
        
        // Getters and Setters
        public Long getTreeId() { return treeId; }
        public void setTreeId(Long treeId) { this.treeId = treeId; }
        
        public Long getTreeNodeId() { return treeNodeId; }
        public void setTreeNodeId(Long treeNodeId) { this.treeNodeId = treeNodeId; }
        
        public Integer getNodeType() { return nodeType; }
        public void setNodeType(Integer nodeType) { this.nodeType = nodeType; }
        
        public String getNodeValue() { return nodeValue; }
        public void setNodeValue(String nodeValue) { this.nodeValue = nodeValue; }
        
        public String getRuleKey() { return ruleKey; }
        public void setRuleKey(String ruleKey) { this.ruleKey = ruleKey; }
        
        public String getRuleDesc() { return ruleDesc; }
        public void setRuleDesc(String ruleDesc) { this.ruleDesc = ruleDesc; }
        
        public List<TreeNodeLinkConfig> getTreeNodeLinks() { return treeNodeLinks; }
        public void setTreeNodeLinks(List<TreeNodeLinkConfig> treeNodeLinks) { this.treeNodeLinks = treeNodeLinks; }
    }
    
    /**
     * 树节点链接配置类
     */
    public static class TreeNodeLinkConfig {
        private Long nodeIdFrom;
        private Long nodeIdTo;
        private Integer ruleLimitType;
        private String ruleLimitValue;
        
        // Getters and Setters
        public Long getNodeIdFrom() { return nodeIdFrom; }
        public void setNodeIdFrom(Long nodeIdFrom) { this.nodeIdFrom = nodeIdFrom; }
        
        public Long getNodeIdTo() { return nodeIdTo; }
        public void setNodeIdTo(Long nodeIdTo) { this.nodeIdTo = nodeIdTo; }
        
        public Integer getRuleLimitType() { return ruleLimitType; }
        public void setRuleLimitType(Integer ruleLimitType) { this.ruleLimitType = ruleLimitType; }
        
        public String getRuleLimitValue() { return ruleLimitValue; }
        public void setRuleLimitValue(String ruleLimitValue) { this.ruleLimitValue = ruleLimitValue; }
    }
    
    /**
     * 缓存配置类
     */
    public static class CacheConfig {
        private Integer maxCacheSize;
        private Boolean enableCache;
        private Integer cacheExpireTime;
        
        // Getters and Setters
        public Integer getMaxCacheSize() { return maxCacheSize; }
        public void setMaxCacheSize(Integer maxCacheSize) { this.maxCacheSize = maxCacheSize; }
        
        public Boolean getEnableCache() { return enableCache; }
        public void setEnableCache(Boolean enableCache) { this.enableCache = enableCache; }
        
        public Integer getCacheExpireTime() { return cacheExpireTime; }
        public void setCacheExpireTime(Integer cacheExpireTime) { this.cacheExpireTime = cacheExpireTime; }
    }
}
